import { Injectable } from '@nestjs/common'
import { ConfigService } from '@nestjs/config'
import { ModuleRef } from '@nestjs/core'
import { CommandContext } from '../interfaces/command-context.interface'
import { Command } from '../interfaces/command.interface'
import { Client, MessageCreateEventContext } from 'discordoo'

@Injectable()
export class CommandsService {
  constructor(
    private readonly moduleRef: ModuleRef,
    private readonly config: ConfigService,
  ) {}

  private readonly commands = new Map<string, Command>()

  register(...commands: Command[]) {
    commands.forEach(c => {
      this.commands.set(c.name, c)
    })
  }

  async handle(context: MessageCreateEventContext, client: Client) {

    const { message } = context

    const ctx: CommandContext = {
      client,
      message,
      moduleRef: this.moduleRef,
      args: message.content.split(/ +/g),
      prefix: this.config.getOrThrow('BOT_PREFIX'),
      token: this.config.getOrThrow('DISCORD_TOKEN'),
    }

    if (!ctx.args[0].startsWith(ctx.prefix)) return // not a command

    // here we separate the command name from the arguments and prefix
    const commandName = ctx.args[0].slice(this.config.getOrThrow('BOT_PREFIX').length)

    const command = this.commands.get(commandName)
    if (command !== undefined) {
      // if command requires owner only, check if the message author is an owner
      if (command.ownersOnly && !this.config.getOrThrow<string>('OWNER_IDS').includes(message.authorId)) {
        return message.reply('no')
      }

      const result = await command.handle(ctx)
      return message.reply(result)
    }
  }
}
